home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Snippets / Solver / SolverPPC1_1.c < prev   
Encoding:
C/C++ Source or Header  |  1996-01-03  |  33.6 KB  |  1,374 lines  |  [TEXT/SPM ]

  1. //• SolverPPC1_1.c
  2. //• ©1995 by Stefan C. Sinclair - All rights reserved.
  3. /* This source code is a stripped down but heavily commented version of my shareware program
  4.    Solver 1.1 . The complete program is available elsewhere in AOL (Utilities Programs,
  5.    Education Programs - well worth the download!).
  6.    I have included all the code I used for it here, minus the routines
  7.    that perform the mathematical computations (that's my secret!). 
  8.    These files show how to:
  9.      a) Support simple text editing in a dialog.
  10.       b) Use simple PICT resources for buttons in a dialog - pretty slick trick I discovered.
  11.       c) Support standard Edit Menu items such as Cut, Copy, Paste, Select All, Clear, and Undo.
  12.       d) demonstrates how to use scroll bars to scroll a large picture in a window
  13.       e) Display numbers in standard or exponential notation depending on their size
  14.       f) Use PowerPC Procedures
  15.       g) Simple error handling
  16.       h) Put an easter egg in your program - cool!
  17.     The included files were compiled with 
  18.    Symantec C++ v8.0.3, but with very little modification,
  19.    they can be made to compile 68K Mac code (I used THINK C v7 for this).
  20.    To make a project from these files, add the following files to your project:
  21.    - SolverPPC1_1.c -> demonstrates how to use a modeless dialog in your application.
  22.       Modeless dialogs are much friendlier to the user than modal dialogs.
  23.    - Help.c -> for online help
  24.    - SolverDemo.π.rsrc
  25.    - ANSI C function library
  26.    - Mac Function Library (these will vary depending on the compiler you are using)
  27.    
  28.    The methods I use are probably not the best, but they get the job done (more or less). I hope
  29.    people will find this helpful - I know I would have a couple years back when I was just starting
  30.    to program on the Mac! Let me know if you find this helpful; I would also be glad to answer any questions
  31.    you might have on this source code. You can reach me via e-mail at: trickys@aol.com 
  32. */
  33.  
  34. #include <math.h>
  35. #include <string.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <ctype.h>
  39. #include <EPPC.h>
  40. #include <GestaltEqu.h>
  41. #include <AppleEvents.h>
  42. #include <Values.h>
  43. #include <Dialogs.h>
  44.  
  45. #define kBaseResID            128
  46.  
  47. #define kMaxNameLength    50 //• Used for registering the shareware app
  48. #define kMinNameLength    12 //• Used for registering the shareware app
  49. #define kPleaseRegisterAlertNum    131
  50. #define kRegistrationDLOG    132
  51.  
  52. #define kMinTextPosition    0
  53. #define kMaxTextPosition    32767
  54.  
  55. #define kMoveToFront        (WindowPtr)-1L
  56. #define kSleep                3600L
  57. #define kLeaveWhereItIs        false
  58. #define kUseDefaultProc        (void *) -1L
  59. #define kMinTextPosition    0
  60. #define kMaxTextPosition    32767
  61. #define kNilSoundChannel    nil
  62. #define kSynchronous        false
  63. #define kGestaltMask        1L
  64. #define kPrecision            17 //• Maximum precision displayed after calculations
  65. #define kUseExponentialNotation    9 //• How big the number gets before exponential notation is used
  66. #define kPI                    3.141592653589793
  67.  
  68. //• Globals
  69. Boolean        gDone = false, gRegistered=false, gSave = false, gRad = true;
  70. MenuHandle        gMenu;
  71. DialogPtr    dialog;
  72. short        itemHit, itemType, vRefNum;
  73. Handle        textItemHandle;
  74. Handle        itemHandle;
  75. Handle        okItemHandle;
  76. Handle        expTextH;
  77. Handle        invTextH;
  78. Handle        ansTextH;
  79. Rect        itemRect;
  80. Str255        expressionStr="\p", saveStr = "\p";
  81. Str63        memStr = "\p", answerStr="\p";
  82. FILE        *cfPtr;
  83. Str255    name;
  84.  
  85. Rect        helpRect;
  86. PicHandle    helpPicture;
  87. WindowPtr    hwindow;
  88.  
  89. //• Function Prototypes
  90. void AEInstallHandlers(void);
  91. pascal OSErr DoOpenApp( AppleEvent *event, AppleEvent *reply, long refcon);
  92. pascal OSErr DoOpenDoc( AppleEvent *event, AppleEvent *reply, long refcon);
  93. pascal OSErr DoPrintDoc( AppleEvent *event, AppleEvent *reply, long refcon);
  94. pascal OSErr DoQuitApp( AppleEvent *event, AppleEvent *reply, long refcon);
  95. OSErr CheckForRequiredParams( AppleEvent *event);
  96. void ToolboxInit(void);
  97. void MenuBarInit(void);
  98. void AEInit(void);
  99. void DoUpdate(EventRecord *eventPtr);
  100. void DoError( Str255 errorString, Boolean fatal);
  101. void HandleMenuChoice( long menuChoice);
  102. void HandleAppleChoice( short item);
  103. void HandleFileChoice( short item);
  104. void DoMainDLOG(void);
  105. void DoEvent( EventRecord *eventPtr);
  106. void HandleMouseDown( EventRecord *eventPtr);
  107. void TypeIt(char c);
  108. void BackIBeam(void);
  109. void HandleEditChoice( short item);
  110. void Credits(void);
  111. short isPressed(unsigned short k );    //• From THINK Reference
  112. Boolean ThisButton(EventRecord *ep, Rect *r);
  113. short doDlgEvt(EventRecord *evp);
  114. void pStrCopy(StringPtr p1, StringPtr p2);
  115.  
  116. /* More Function prototypes */
  117. double    Solve(char infixStr[]);
  118. void    EmptyString(char *string, short num);
  119. void    SaveNew(void);
  120. void Registration(void);
  121. Boolean    isRegistered(void);
  122. void PleaseRegister(void);
  123. void Help(void);
  124.  
  125. pascal OSErr SetDialogDefaultItem(DialogPtr theDialog, short item)
  126.     = { 0x303C, 0x0304, 0xAA68};
  127. pascal OSErr SetDialogCancelItem(DialogPtr theDialog, short item)
  128.     = {0x303C, 0x0305, 0xAA68};
  129. pascal OSErr SetDialogTracksCursor(DialogPtr theDialog, Boolean tracks)
  130.     = {0x303C, 0x0306, 0xAA68};
  131.  
  132. main()
  133. {
  134.     OSErr    err;
  135.     FInfo    fndrInfo;
  136.     
  137.     ToolboxInit();
  138.     AEInit(); //• Support the required Apple Events - very important!
  139.     //• gRegistered = isRegistered();
  140.     gRegistered = false; //• for this demo's purposes.
  141.     if(!gRegistered)
  142.     {
  143.         PleaseRegister();
  144.         if(gRegistered)
  145.             DoError("\pYou are now a registered user!", false);
  146.     }
  147.     
  148.     MenuBarInit();
  149.     //• Next, load the Help window, but don't show it until needed.
  150.     if ( ( hwindow = GetNewWindow( kBaseResID, nil,
  151.             kMoveToFront ) ) == nil )
  152.         DoError( "\pCan't Load WIND resource!", true );
  153.     //• Online help consists of a very tall PICT
  154.     if ( ( helpPicture = (PicHandle)GetResource( 'PICT', 150) ) == nil )
  155.         DoError( "\pCan't Load Help PICT resource!", true );
  156.     //• helpRect is set to the actual size of the PICT
  157.     helpRect.top = hwindow->portRect.top + 2;
  158.     helpRect.left = hwindow->portRect.left + 2;
  159.     helpRect.right = helpRect.left + 313;
  160.     helpRect.bottom = helpRect.top + 812;
  161.     //• Set up help window scroll bars
  162.     SetUpScrollBar( hwindow );
  163.     //• Enter main program
  164.     if(!gDone)
  165.         DoMainDLOG();
  166.     /* DoMainDLOG will get called more later on. The strategy I employ here is to exit and dispose of
  167.     the main dialog every time some other dialog or alert is brought up. Afterwards, DoMainDLOG() is
  168.     called again. Sort of strange, but it works pretty good. */
  169.     DisposeDialog(dialog); //• Here we are done for good
  170.     if(!gRegistered)
  171.         PleaseRegister();
  172.     //• In registered versions, the output gets saved to a TeachText file if desired - pretty usefull.
  173.     if(gSave)
  174.     {
  175.         fclose(cfPtr);
  176.         err = GetFInfo(name,vRefNum,&fndrInfo);
  177.         if(err)
  178.             SysBeep(30);
  179.         fndrInfo.fdType = 'TEXT';
  180.         fndrInfo.fdCreator = 'ttxt';
  181.         err = SetFInfo(name,vRefNum,&fndrInfo);
  182.         if(err)
  183.             SysBeep(30);
  184.     }
  185.     return 0; //• All finished.
  186. }
  187.  
  188. //• ToolboxInit() - pretty straight forward
  189. void ToolboxInit()
  190. {
  191.     InitGraf((Ptr) &qd.thePort);
  192.     InitFonts();
  193.     InitWindows();
  194.     InitMenus();
  195.     FlushEvents(everyEvent,0);
  196.     TEInit();
  197.     InitDialogs(0L);
  198.     InitCursor();
  199. }
  200.  
  201. //• MenuBarInit() - pretty straight forward
  202. void MenuBarInit( void)
  203. {
  204.     Handle    menuBar;
  205.     
  206.     menuBar = GetNewMBar(128);
  207.     SetMenuBar( menuBar);
  208.     
  209.     gMenu = GetMenu( 128); // apple
  210.     AddResMenu( gMenu, 'DRVR');
  211.     
  212.     gMenu = GetMenu( 129); // File
  213.     InsertMenu( gMenu, -1);
  214.     if(!gRegistered)
  215.         DisableItem(gMenu, 1);
  216.  
  217.     gMenu = GetMenu( 130); // Edit
  218.     InsertMenu( gMenu, -1);
  219.     
  220.     DrawMenuBar();
  221. }
  222.  
  223. //• AEInit() - pretty straight forward
  224. void AEInit( void)
  225. {
  226.     OSErr    err;
  227.     long    feature;
  228.     
  229.     err = Gestalt(gestaltAppleEventsAttr, &feature);
  230.     if(err != noErr)
  231.         DoError("\pError returned by gestalt!", true);
  232.     if(!(feature & (kGestaltMask << gestaltAppleEventsPresent)))
  233.         DoError("\pApple Events not supported!", true);
  234.     AEInstallHandlers();
  235. }
  236.  
  237. //• AEInstallHandlers() - this version is written for compiling PPC native code
  238. void AEInstallHandlers(void)
  239. {
  240.     OSErr    err;
  241.     /* install the required apple event handlers */
  242.     AEEventHandlerUPP OPENae, QUITae, STARTae, PRINTae;
  243.     
  244.     /* must use these for PPC proc pointers */
  245.     OPENae = NewAEEventHandlerProc ((ProcPtr) &DoOpenDoc);
  246.     QUITae = NewAEEventHandlerProc ((ProcPtr) &DoQuitApp);
  247.     STARTae = NewAEEventHandlerProc ((ProcPtr) &DoOpenApp);
  248.     PRINTae = NewAEEventHandlerProc ((ProcPtr) &DoPrintDoc);
  249.     err = AEInstallEventHandler( kCoreEventClass, kAEOpenApplication,STARTae, 0L, false);
  250.     if(err != noErr)
  251.         DoError("\pError installing 'open app' handler!", true);
  252.     err = err = AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments, OPENae, 0L, false);
  253.     if(err != noErr)
  254.         DoError("\pError installing 'open doc' handler!", true);
  255.     err = err = AEInstallEventHandler( kCoreEventClass, kAEPrintDocuments, PRINTae, 0L, false);
  256.     if(err != noErr)
  257.         DoError("\pError installing 'print doc' handler!", true);
  258.     err = err = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, QUITae, 0L, false);
  259.     if(err != noErr)
  260.         DoError("\pError installing 'quit app' handler!", true);
  261. }
  262.  
  263. pascal OSErr DoOpenApp( AppleEvent *event, AppleEvent *reply, long refcon)
  264. {
  265.     //• Do nothing. Normally, you might open a new Untitled window or something.
  266.     return noErr;
  267. }
  268.  
  269. pascal OSErr DoOpenDoc( AppleEvent *event, AppleEvent *reply, long refcon)
  270. {
  271.     //• Again nothing will ever happen (this routine won't get called in this program, but it's still helpful to read)
  272.     OSErr        err;
  273.     FSSpec        fileSpec;
  274.     long        i, numDocs;
  275.     DescType    returnedType;
  276.     AEKeyword    keywd;
  277.     Size        actualSize;
  278.     AEDescList    docList = {typeNull, nil};    // Get the direct parameter-a descriptor list-and put into docList
  279.     
  280.     err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docList);
  281.     err = CheckForRequiredParams( event);    // Check for missing required parameters
  282.     if(err)
  283.     {
  284.         err = AEDisposeDesc( &docList);
  285.         return err;
  286.     }
  287.     err = AECountItems( &docList, &numDocs);    // Count #of descriptor records in the list
  288.     if(err)                                    // Should be at least 1 since we got called & no error.
  289.     {
  290.         err = AEDisposeDesc( &docList);
  291.         return err;
  292.     }
  293.     // Now get each descriptor record, coerce data to an FSSpec record, & open the file
  294.     for( i = 1; i <= numDocs; i++)
  295.     {
  296.         err = AEGetNthPtr( &docList, i, typeFSS, &keywd, &returnedType, (Ptr)&fileSpec, sizeof(fileSpec), &actualSize);
  297.         //OpenDocument( &fileSpec); <- normally would do something like this
  298.         //• See above! DoMainDLOG();
  299.     }
  300.     err = AEDisposeDesc( &docList);
  301.     return err;
  302. }
  303.  
  304.  
  305. OSErr CheckForRequiredParams( AppleEvent *appleEventPtr)
  306. {
  307.     DescType        returnedType;
  308.     Size            actualSize;
  309.     OSErr            err;
  310.     
  311.     err = AEGetAttributePtr( appleEventPtr, keyMissedKeywordAttr, typeWildCard, &returnedType, nil, 0, &actualSize);
  312.     //• Looks for specified attribute, returns attribute status as an error
  313.     
  314.     if( err == errAEDescNotFound)
  315.         return noErr;
  316.     else if( err == noErr)
  317.         return errAEParamMissed;
  318.     else
  319.         return err;
  320. }
  321.  
  322. pascal OSErr DoPrintDoc( AppleEvent *event, AppleEvent *reply, long refcon)
  323. {
  324.     return noErr;
  325. }
  326.  
  327. pascal OSErr DoQuitApp( AppleEvent *event, AppleEvent *reply, long refcon)
  328. {
  329.     gDone = true;
  330.     return noErr;
  331. }
  332.  
  333. /********** DoError ********************/
  334. /* Pretty simple. Should probably check to make sure that Alert #128 is really present, though*/
  335. void DoError( Str255 errorString, Boolean fatal)
  336. {
  337.     ParamText( errorString, "\p", "\p", "\p");
  338.     NoteAlert( 128, nil);
  339.     if( fatal == true)
  340.         ExitToShell();
  341. }
  342.  
  343. //• pStrCopy()
  344. void pStrCopy (StringPtr p1, StringPtr p2)
  345. /* copies a pascal string from p1 to p2 . "Borrowed" from THINK Reference*/
  346. {
  347.     register int len;
  348.     
  349.     len = *p2++ = *p1++;
  350.     while (--len >= 0)
  351.         *p2++ = *p1++;
  352. }
  353.  
  354. //• HandleMenuChoice()
  355. void HandleMenuChoice( long menuChoice)
  356. {
  357.     short    menu;
  358.     short    item;
  359.     
  360.     if( menuChoice != 0)
  361.     {
  362.         menu = HiWord( menuChoice);
  363.         item = LoWord( menuChoice);
  364.         switch( menu)
  365.         {
  366.             case 128: // apple
  367.                 HandleAppleChoice( item);
  368.                 break;
  369.             case 129: // File
  370.                 HandleFileChoice( item);
  371.                 break;
  372.             case 130:
  373.                 HandleEditChoice(item); 
  374.                 break;
  375.         }
  376.         HiliteMenu(0);
  377.     }
  378. }
  379.  
  380. //• HandleAppleChoice
  381. void HandleAppleChoice( short item)
  382. {
  383.     MenuHandle    appleMenu;
  384.     Str255        accName;
  385.     short        accNumber;
  386.     
  387.     switch( item)
  388.     {
  389.         case 1:
  390.             Credits(); //• All about my wonderful program
  391.             break;
  392.         default:
  393.             appleMenu = GetMHandle( 128);
  394.             GetItem( appleMenu, item, accName);
  395.             accNumber = OpenDeskAcc( accName);
  396.             break;
  397.     }
  398. }
  399.  
  400. //• HandleFileChoice()
  401. void HandleFileChoice( short item)
  402. {    
  403.     switch( item)
  404.     {
  405.         case 1: // Save to file - available only to registered users
  406.             if(!gSave)
  407.             {
  408.                 gSave = true;
  409.                 SaveNew();
  410.             }
  411.             break;
  412.         case 3: // Quit
  413.             gDone = true;
  414.             break;
  415.         default:
  416.             break;
  417.     }
  418. }
  419.  
  420. //• SaveNew()
  421. void SaveNew(void)
  422. {
  423.     OSErr     err;
  424.     SFReply  theFile;
  425.     short     i, ie, k, fRefNum;
  426.     Point    where;    /* where to display dialog */
  427.  
  428. /* Many of the File Creating & Writing Routines used here are
  429.    specific to the Macintosh */
  430.    if(gRegistered)
  431.    {
  432.         where.h = 20;
  433.         where.v = 20;
  434.         SFPutFile(where, "\pSave Solver output as: ", "\pUntitled", nil, &theFile);
  435.         if (!theFile.good)
  436.             DoError("\pError creating new file.", true);
  437.         vRefNum = theFile.vRefNum;
  438.         err = Create(theFile.fName, theFile.vRefNum, 'ttxt', 'TEXT');
  439.         if(err)
  440.             DoError("\pError creating the new file.", true);
  441.         err = SetVol(NULL, theFile.vRefNum);
  442.         pStrCopy(theFile.fName, name);
  443.         if (err)
  444.             DoError("\pCould not Set Volume.", true);
  445.         cfPtr = fopen (p2cstr(name), "w");
  446.         if (cfPtr == NULL)
  447.             DoError("\pCan't open the new file.", true);
  448.         c2pstr((char *)name); //• Don't forget to convert back to a Pascal string!
  449.     }
  450.     else
  451.         SysBeep(30);
  452. }
  453.  
  454. //• HandleEditChoice()
  455. void HandleEditChoice( short item)
  456. {    
  457.     short i;
  458.     
  459.     switch( item)
  460.     {
  461.         case 1: // Undo
  462.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  463.             GetIText( expTextH, expressionStr);
  464.             SetIText(expTextH, saveStr);
  465.             //• save current entry in 'saveStr' in case user wants to 'Undo' later on.
  466.             //• That is how the Undo function is supported.
  467.             for(i=0; i<255; i++)
  468.                 saveStr[i] = expressionStr[i];
  469.             break;
  470.         case 3: // Cut - made very easy in a dialog
  471.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  472.             GetIText( expTextH, expressionStr);
  473.             //• save current entry in case user wants to 'Undo' later on.
  474.             for(i=0; i<255; i++)
  475.                 saveStr[i] = expressionStr[i];
  476.             DlgCut(dialog);
  477.             break;
  478.         case 4: // Copy
  479.             DlgCopy(dialog);
  480.             break;
  481.         case 5: // Paste
  482.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  483.             GetIText( expTextH, expressionStr);
  484.             //• save current entry in case user wants to 'Undo' later on.
  485.             for(i=0; i<255; i++)
  486.                 saveStr[i] = expressionStr[i];
  487.             DlgPaste(dialog);
  488.             break;
  489.         case 6: // Clear
  490.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  491.             GetIText( expTextH, expressionStr);
  492.             //• save current entry in case user wants to 'Undo' later on.
  493.             for(i=0; i<255; i++)
  494.                 saveStr[i] = expressionStr[i];
  495.             DlgDelete(dialog);
  496.             break;
  497.         case 8: //• Select All
  498.             SelIText( dialog, 18, kMinTextPosition, kMaxTextPosition);
  499.             break;
  500.     }
  501. }
  502.  
  503.  
  504. //• DoMainDLOG()
  505. void DoMainDLOG(void)
  506. {
  507.     EventRecord        event;
  508.     Boolean        evtOccured;
  509.     short            i=0;
  510.     char            cStr[256] = "";
  511.     
  512.     dialog = GetNewDialog(133, nil, kMoveToFront);
  513.     SetPort(dialog);
  514.     ShowWindow(dialog);
  515.     
  516.     GetDItem( dialog, 17, &itemType, &okItemHandle, &itemRect);
  517.     GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  518.     //SelIText( dialog, 18, kMinTextPosition, kMaxTextPosition);
  519.     GetDItem( dialog, 19, &itemType, &ansTextH, &itemRect);
  520.     GetDItem( dialog, 20, &itemType, &itemHandle, &itemRect);
  521.     GetDItem( dialog, 21, &itemType, &itemHandle, &itemRect);
  522.     GetDItem( dialog, 22, &itemType, &itemHandle, &itemRect);
  523.     
  524.     SetDialogTracksCursor(dialog, true);
  525.     
  526.     //• There may be something stored in 'saveStr[]', as this routine will usually get called several times.
  527.     GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  528.     GetIText( expTextH, expressionStr);
  529.     SetIText(expTextH, "\p");
  530.     strcpy(cStr, p2cstr(saveStr));
  531.     while(cStr[i] != '\0')
  532.         TypeIt(cStr[i++]);
  533.     c2pstr((char *)saveStr); //• Don't forget to change it back!
  534.     
  535.             
  536.     
  537.     while( !gDone)
  538.     {
  539.         evtOccured =  GetNextEvent( everyEvent, &event);
  540.         if (evtOccured)
  541.         {
  542.             /* Important to save this first, in case dialog is disposed of and then created again */
  543.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  544.             GetIText( expTextH, expressionStr);
  545.             
  546.             switch ( event.what ) 
  547.             {
  548.                 case mouseDown:
  549.                     HandleMouseDown(&event);
  550.                     break;
  551.                 case updateEvt:
  552.                     DoUpdate(&event);
  553.                     break;
  554.                 case kHighLevelEvent:
  555.                     AEProcessAppleEvent(&event);
  556.                     break;
  557.                     /* ... process non-dialog events ... */
  558.  
  559.             }    /* end of switch */
  560.             if ( IsDialogEvent( &event) )
  561.                 doDlgEvt( &event );
  562.         }    /* end of if */
  563.         //• Adding this line causes the I-beam to flash as expected
  564.         else if(IsDialogEvent(&event))
  565.             doDlgEvt( &event );
  566.             
  567.     } /* end of while */
  568. }
  569.  
  570. /* CODE EXAMPLE #1 - again from THINK Reference */
  571. short isPressed(unsigned short k )
  572. // k =  any keyboard scan code, 0-127
  573. {
  574.     unsigned char km[16];
  575.  
  576.     GetKeys( (long *) km);
  577.     return ( ( km[k>>3] >> (k & 7) ) & 1);
  578. }
  579.  
  580. //• ThisButton() - checks to see if the button in my main dialog gets pressed.
  581. Boolean ThisButton(EventRecord *ep, Rect *r)
  582. {
  583.     Point        newPoint, oldPoint;
  584.     
  585.     newPoint = oldPoint = ep->where;
  586.     InvertRect(r); //• My buttons are really just PICTs in the DITL, with the 'Enabled'
  587.     //• Box checked - that is a little trick I discovered by accident. Checking the Enabled box
  588.     //• in the DITL resource lets you detect events in those items! Cool.
  589.     while(WaitMouseUp())
  590.     {
  591.         GetMouse(&newPoint);
  592.         if(DeltaPoint(oldPoint, newPoint))
  593.           ;
  594.     }
  595.     InvertRect(r); //• Put it back to normal
  596.     return(PtInRect(newPoint, r) ? true : false);
  597. }
  598.               
  599. //• doDlgEvt() - my main event handling routine. Many of the variables you see
  600. //• don't get used in this demo source code though. This routine is the guts of the program interface.
  601. short doDlgEvt(EventRecord *evp)
  602. {
  603.     DialogPtr    whichDlg;
  604.     WindowPtr    whichWindow;
  605.     Handle        itemH;
  606.     short        thePart, k=0, accountForNegative=0, exponent=0;
  607.     char        theKey;
  608.     long        integer, fraction;
  609.     long        i=0, decimalPlace[kPrecision] = {0};
  610.     double        dInteger, dFraction, dDecimal, portion;
  611.     double        theAnswer = 0, dj=0, log10Answer = 0;
  612.     Str255        pStr1, pStr2, EmptyStr = "\p";
  613.     char        cStr1[256], cStr2[256];
  614.     char        decimal[] = ".", E[] = "E", minusSign[] = "-", plusSign[] = "+";
  615.     Point        oldPoint;
  616.             
  617.     if ( evp->what == keyDown )
  618.     {
  619.         if ( evp->modifiers & cmdKey )
  620.         {    /*command key pressed - handle accordingly. */
  621.             theKey =  evp->message & charCodeMask;
  622.             if( (theKey == 'Z') || (theKey == 'z') )
  623.                 HandleEditChoice(1);
  624.             else if( (theKey == 'C') || (theKey == 'c') )/* do command-C via DlgCopy */
  625.                 HandleEditChoice(4);
  626.             else if( (theKey == 'X') || (theKey == 'x') )/* do command-X via DlgCut */
  627.                 HandleEditChoice(3);
  628.             else if( (theKey == 'V') || (theKey == 'v') )/* do command-V via DlgPaste */
  629.                 HandleEditChoice(5);
  630.             else if( (theKey == 'A') || (theKey == 'a') )/* do command-A */
  631.                 HandleEditChoice(8);
  632.             else if( (theKey == 'Q') || (theKey == 'q') )/* do command-Q */
  633.                 gDone = true;
  634.  
  635.             /*.. here one would check for and process other command-shifted keys if needed ... */
  636.  
  637.             return(0);
  638.                     /* the moral here is that you don't let unwanted command-keys into DialogSelect() */
  639.         }
  640.     }
  641.     
  642.     if (DialogSelect( evp, &whichDlg, &itemHit ) == FALSE ) //• Nothing was hit.
  643.         return(0);        /* no extra work needed ,  just return */
  644.  
  645.     if ( whichDlg == dialog && itemHit != 0)
  646.     {            /* process the interaction */
  647.         GetDItem( dialog, itemHit, &itemType, &itemH, &itemRect);
  648.         switch(itemHit)
  649.         {
  650.             case 1://• ABS
  651.             //• They clicked in this Rect!
  652.               if(ThisButton(evp, &itemRect))
  653.               {
  654.                 TypeIt('a');
  655.                 TypeIt('b');
  656.                 TypeIt('s');
  657.                 BackIBeam();
  658.             }
  659.             break;
  660.             case 2:    //• COS
  661.             //• They clicked in this Rect!
  662.               if(ThisButton(evp, &itemRect))
  663.               {
  664.                 TypeIt('c');
  665.                 TypeIt('o');
  666.                 TypeIt('s');
  667.                 BackIBeam();
  668.             }
  669.             break;
  670.             case 3:    //• SIN
  671.             //• They clicked in this Rect!
  672.               if(ThisButton(evp, &itemRect))
  673.               {
  674.                 TypeIt('s');
  675.                 TypeIt('i');
  676.                 TypeIt('n');
  677.                 BackIBeam();
  678.             }
  679.             break;
  680.             case 4:    //• TAN
  681.             //• They clicked in this Rect!
  682.               if(ThisButton(evp, &itemRect))
  683.               {
  684.                 TypeIt('t');
  685.                 TypeIt('a');
  686.                 TypeIt('n');
  687.                 BackIBeam();
  688.             }
  689.             break;
  690.             case 5:    //• COSH
  691.             //• They clicked in this Rect!
  692.               if(ThisButton(evp, &itemRect))
  693.               {
  694.                 TypeIt('c');
  695.                 TypeIt('o');
  696.                 TypeIt('s');
  697.                 TypeIt('h');
  698.                 BackIBeam();
  699.             }
  700.             break;
  701.             case 6:    //• SINH
  702.             //• They clicked in this Rect!
  703.               if(ThisButton(evp, &itemRect))
  704.               {
  705.                 TypeIt('s');
  706.                 TypeIt('i');
  707.                 TypeIt('n');
  708.                 TypeIt('h');
  709.                 BackIBeam();
  710.             }
  711.             break;
  712.             case 7:    //• TANH
  713.             //• They clicked in this Rect!
  714.               if(ThisButton(evp, &itemRect))
  715.               {
  716.                 TypeIt('t');
  717.                 TypeIt('a');
  718.                 TypeIt('n');
  719.                 TypeIt('h');
  720.                 BackIBeam();
  721.             }
  722.             break;
  723.             case 8:    //• ACOS
  724.             //• They clicked in this Rect!
  725.               if(ThisButton(evp, &itemRect))
  726.               {
  727.                 TypeIt('a');
  728.                 TypeIt('c');
  729.                 TypeIt('o');
  730.                 TypeIt('s');
  731.                 BackIBeam();
  732.             }
  733.             break;
  734.             case 9:    //• ASIN
  735.             //• They clicked in this Rect!
  736.               if(ThisButton(evp, &itemRect))
  737.               {
  738.                 TypeIt('a');
  739.                 TypeIt('s');
  740.                 TypeIt('i');
  741.                 TypeIt('n');
  742.                 BackIBeam();
  743.             }
  744.             break;
  745.             case 10:    //• ATAN
  746.             //• They clicked in this Rect!
  747.               if(ThisButton(evp, &itemRect))
  748.               {
  749.                 TypeIt('a');
  750.                 TypeIt('t');
  751.                 TypeIt('a');
  752.                 TypeIt('n');
  753.                 BackIBeam();
  754.             }
  755.             break;
  756.             case 11:    //• EXP
  757.             //• They clicked in this Rect!
  758.               if(ThisButton(evp, &itemRect))
  759.               {
  760.                 TypeIt('e');
  761.                 TypeIt('x');
  762.                 TypeIt('p');
  763.                 BackIBeam();
  764.             }
  765.             break;
  766.             case 12:    //• LN
  767.             //• They clicked in this Rect!
  768.               if(ThisButton(evp, &itemRect))
  769.               {
  770.                 TypeIt('l');
  771.                 TypeIt('n');
  772.                 BackIBeam();
  773.             }
  774.             break;
  775.             case 13:    //• LOG
  776.             //• They clicked in this Rect!
  777.               if(ThisButton(evp, &itemRect))
  778.               {
  779.                 TypeIt('l');
  780.                 TypeIt('o');
  781.                 TypeIt('g');
  782.                 BackIBeam();
  783.             }
  784.             break;
  785.             case 14:    //• SQRT
  786.             //• They clicked in this Rect!
  787.               if(ThisButton(evp, &itemRect))
  788.               {
  789.                 TypeIt('s');
  790.                 TypeIt('q');
  791.                 TypeIt('r');
  792.                 TypeIt('t');
  793.                 BackIBeam();
  794.             }
  795.             break;
  796.             case 15:    //• π
  797.             //• They clicked in this Rect!
  798.               if(ThisButton(evp, &itemRect))
  799.               {
  800.                 TypeIt('3');
  801.                 TypeIt('.');
  802.                 TypeIt('1');
  803.                 TypeIt('4');
  804.                 TypeIt('1');
  805.                 TypeIt('5');
  806.                 TypeIt('9');
  807.                 TypeIt('2');
  808.                 TypeIt('6');
  809.                 TypeIt('5');
  810.                 TypeIt('4');
  811.             }
  812.             break;
  813.             case 16:    //• e
  814.             //• They clicked in this Rect!
  815.               if(ThisButton(evp, &itemRect))
  816.               {
  817.                 TypeIt('2');
  818.                 TypeIt('.');
  819.                 TypeIt('7');
  820.                 TypeIt('1');
  821.                 TypeIt('8');
  822.                 TypeIt('2');
  823.                 TypeIt('8');
  824.                 TypeIt('1');
  825.                 TypeIt('8');
  826.                 TypeIt('2');
  827.                 TypeIt('8');
  828.             }
  829.             break;
  830.         case 17:    //• Evaluate 
  831.         //• They clicked in this Rect!
  832.               if(ThisButton(evp, &itemRect))
  833.               {
  834.             GetDItem( dialog, 18, &itemType, &expTextH, &itemRect);
  835.             GetIText( expTextH, expressionStr);
  836.             GetDItem( dialog, 19, &itemType, &ansTextH, &itemRect);
  837.             strcpy(cStr1,p2cstr(expressionStr));
  838.             if(cStr1[0] == '\0')
  839.             {
  840.                 cStr1[0] = '0';
  841.                 cStr1[1] = '\0';
  842.             }
  843.             theAnswer = Solve(cStr1); //• This routine is my trade secret!
  844.             if(gSave)
  845.                 fprintf(cfPtr, "%s =\n", cStr1);
  846.             /* I'm sure there is probably a better way to do this, but this is all I could
  847.                come up with... */
  848.             log10Answer = log10(fabs(theAnswer));
  849.             for(i=0; i<=255; i++)
  850.                 cStr1[1] = 0;
  851.             cStr1[0] = '\0';
  852.             /* make sure negative sign stays there */
  853.             if(theAnswer <  0)
  854.             {
  855.                 cStr1[0] = '-';
  856.                 cStr1[1] = '\0';
  857.                 accountForNegative = 1;
  858.             }
  859.             //••• Do we need exponential notation? •••
  860.             exponent = 0 + fabs(log10Answer);
  861.             if(exponent >= kUseExponentialNotation)
  862.             {
  863.                 if(log10Answer <  0) //• Negative exponent?
  864.                 {
  865.                 //• use next 'smallest' integer, and it's negative.
  866.                     exponent = 0 - floor(log10Answer);
  867.                     theAnswer = theAnswer*pow(10, exponent);//••• theAnswer IS CHANGED!
  868.                 }
  869.                 else
  870.                     theAnswer = theAnswer/pow(10, exponent);//••• theAnswer IS CHANGED!
  871.                 dFraction = fabs(modf(theAnswer, &dInteger));
  872.                 integer = 0 + fabs(dInteger);
  873.                 NumToString(integer, pStr1);
  874.                 strcat(cStr1, p2cstr(pStr1));
  875.                 k = strlen(cStr1) - accountForNegative;
  876.                 strcat(cStr1, decimal);
  877.                 /* now add maximum possible decimal places - as acurate as it gets now! */
  878.                 dj = 10;
  879.                 for(i=0; i< (kPrecision-k); i++)
  880.                 {
  881.                     decimalPlace[i] = floor(dFraction * dj);
  882.                     /* subtract off the 'enlarged' portion */
  883.                     dDecimal = decimalPlace[i];
  884.                     portion = dDecimal / dj;
  885.                     dFraction -= portion;
  886.                     NumToString(decimalPlace[i], pStr2);
  887.                     strcpy(cStr2, p2cstr(pStr2));
  888.                     strcat(cStr1, cStr2);
  889.                     dj*=10;
  890.                 }
  891.                 NumToString(exponent, pStr1);
  892.                 strcat(cStr1, E);
  893.                 if(log10Answer <  0)
  894.                     strcat(cStr1, minusSign);
  895.                 else
  896.                     strcat(cStr1, plusSign);
  897.                 strcat(cStr1, p2cstr(pStr1));
  898.                 pStrCopy(c2pstr(cStr1), answerStr); /* answer, w/ E+/- */
  899.                 SetIText(ansTextH, answerStr);
  900.                 if(gSave)
  901.                 {
  902.                     fprintf(cfPtr, "\t%s\n", p2cstr(answerStr));
  903.                 }
  904.             }
  905.             else //• No exponential notation
  906.             {
  907.                 dFraction = fabs(modf(theAnswer, &dInteger));
  908.                 integer = 0 + fabs(dInteger);
  909.                 NumToString(integer, pStr1);
  910.                 strcat(cStr1, p2cstr(pStr1));
  911.                 k = strlen(cStr1) - accountForNegative;
  912.                 strcat(cStr1, decimal);
  913.                 /* now add maximum possible decimal places - as acurate as it gets now! */
  914.                 dj = 10;
  915.                 for(i=0; i< (kPrecision-k); i++)
  916.                 {
  917.                     decimalPlace[i] = floor(dFraction * dj);
  918.                     /* subtract off the 'enlarged' portion */
  919.                     dDecimal = decimalPlace[i];
  920.                     portion = dDecimal / dj;
  921.                     dFraction -= portion;
  922.                     NumToString(decimalPlace[i], pStr2);
  923.                     strcpy(cStr2, p2cstr(pStr2));
  924.                     strcat(cStr1, cStr2);
  925.                     dj*=10;
  926.                 }
  927.                 pStrCopy(c2pstr(cStr1), answerStr); /* answer! */
  928.                 SetIText(ansTextH, answerStr);
  929.                 if(gSave)
  930.                 {
  931.                     fprintf(cfPtr, "\t%s\n", p2cstr(answerStr));
  932.                 }
  933.             }
  934.         } //• End of if(ThisButton())
  935.         break;
  936.         case 18:
  937.         break;
  938.         case 19:
  939.         break;
  940.         case 20: //• Help Button
  941.             Help();
  942.         break;
  943.         case 21:
  944.         break;
  945.         case 22:    //• E
  946.         //• They clicked in this Rect!
  947.         if(ThisButton(evp, &itemRect))
  948.               TypeIt('E');
  949.         break;
  950.         case 23:    //• Clear
  951.             //• They clicked in this Rect!
  952.               if(ThisButton(evp, &itemRect))
  953.               {
  954.                   HandleEditChoice(8); //• Select All
  955.                 HandleEditChoice(6); //• Clear
  956.             }
  957.         break;
  958.         case 24: //• RAD/DEG toggle
  959.         //• They clicked in this Rect!
  960.         if(ThisButton(evp, &itemRect))
  961.         {
  962.           if(gRad)
  963.             {
  964.                 SetIText(itemH, "\pdeg"); //• use degrees for trig fxns
  965.                 gRad = false;
  966.             }
  967.             else
  968.             {
  969.                 SetIText(itemH, "\prad"); //• use radians for trig fxns
  970.                 gRad = true;
  971.             }
  972.         }
  973.         break;
  974.         case 25:    //• ()
  975.         //• They clicked in this Rect!
  976.               if(ThisButton(evp, &itemRect))
  977.                   BackIBeam();
  978.             break;
  979.         case 26: //• RCL
  980.         //• They clicked in this Rect!
  981.               if(ThisButton(evp, &itemRect))
  982.               {
  983.                   strcpy(cStr1, p2cstr(memStr)); //• memStr is the calculator's memory.
  984.                   i=0;
  985.                   while(cStr1[i] != '\0')
  986.                       TypeIt(cStr1[i++]);
  987.                   c2pstr((char *)memStr);
  988.               }
  989.         break;
  990.         case 27: //• M+
  991.         //• They clicked in this Rect!
  992.               if(ThisButton(evp, &itemRect))
  993.                   pStrCopy(answerStr, memStr);
  994.         break;
  995.         case 28: //• +
  996.         //• They clicked in this Rect!
  997.               if(ThisButton(evp, &itemRect))
  998.                   TypeIt('+');
  999.         break;
  1000.         case 29: //• -
  1001.         //• They clicked in this Rect!
  1002.               if(ThisButton(evp, &itemRect))
  1003.                   TypeIt('-');
  1004.         break;
  1005.         case 30: //• x
  1006.         //• They clicked in this Rect!
  1007.               if(ThisButton(evp, &itemRect))
  1008.                   TypeIt('*');
  1009.         break;
  1010.         case 31: //• ÷
  1011.         //• They clicked in this Rect!
  1012.               if(ThisButton(evp, &itemRect))
  1013.                   TypeIt('/');
  1014.         break;
  1015.         case 32: //• ^
  1016.         //• They clicked in this Rect!
  1017.               if(ThisButton(evp, &itemRect))
  1018.                   TypeIt('^');
  1019.         break;
  1020.         case 33: //• %
  1021.         //• They clicked in this Rect!
  1022.               if(ThisButton(evp, &itemRect))
  1023.                   TypeIt('%');
  1024.         break;
  1025.         case 34:    //• .
  1026.         //• They clicked in this Rect!
  1027.               if(ThisButton(evp, &itemRect))
  1028.                   TypeIt('.');
  1029.         break;
  1030.         case 35:    //• 0
  1031.         //• They clicked in this Rect!
  1032.               if(ThisButton(evp, &itemRect))
  1033.                   TypeIt('0');
  1034.             break;
  1035.         case 36:    //• 1
  1036.         //• They clicked in this Rect!
  1037.               if(ThisButton(evp, &itemRect))
  1038.                   TypeIt('1');
  1039.             break;
  1040.         case 37:    //• 2
  1041.         //• They clicked in this Rect!
  1042.               if(ThisButton(evp, &itemRect))
  1043.                   TypeIt('2');
  1044.             break;
  1045.         case 38:    //• 3
  1046.         //• They clicked in this Rect!
  1047.               if(ThisButton(evp, &itemRect))
  1048.                   TypeIt('3');
  1049.             break;
  1050.         case 39:    //• 4
  1051.         //• They clicked in this Rect!
  1052.               if(ThisButton(evp, &itemRect))
  1053.                   TypeIt('4');
  1054.             break;
  1055.         case 40:    //• 5
  1056.         //• They clicked in this Rect!
  1057.               if(ThisButton(evp, &itemRect))
  1058.                   TypeIt('5');
  1059.             break;
  1060.         case 41:    //• 6
  1061.         //• They clicked in this Rect!
  1062.               if(ThisButton(evp, &itemRect))
  1063.                   TypeIt('6');
  1064.             break;
  1065.         case 42:    //• 7
  1066.         //• They clicked in this Rect!
  1067.               if(ThisButton(evp, &itemRect))
  1068.                   TypeIt('7');
  1069.             break;
  1070.         case 43:    //• 8
  1071.         //• They clicked in this Rect!
  1072.               if(ThisButton(evp, &itemRect))
  1073.                   TypeIt('8');
  1074.             break;
  1075.         case 44:    //• 9
  1076.         //• They clicked in this Rect!
  1077.               if(ThisButton(evp, &itemRect))
  1078.                   TypeIt('9');
  1079.             break;
  1080.         default:
  1081.             break;
  1082.         } //• End switch
  1083.     }
  1084.     return 1;
  1085. }
  1086.  
  1087. //• DoUpdate() - pretty simple!
  1088. void DoUpdate( EventRecord *eventPtr)
  1089. {
  1090.     UpdateDialog(dialog, dialog->visRgn);
  1091. }
  1092.  
  1093. //• HandleMouseDown()
  1094. void HandleMouseDown( EventRecord *eventPtr)
  1095. {
  1096.     WindowPtr        whichWindow;
  1097.     short            thePart;
  1098.     long            menuChoice;
  1099.     
  1100.     thePart = FindWindow( eventPtr->where, &whichWindow);
  1101.     switch( thePart)
  1102.     {
  1103.         case inMenuBar:
  1104.             menuChoice = MenuSelect( eventPtr->where);
  1105.             HandleMenuChoice( menuChoice);
  1106.             break;
  1107.         case inSysWindow:
  1108.             SystemClick( eventPtr, whichWindow);
  1109.             break;
  1110.         case inContent:
  1111.             break;
  1112.         case inDrag:
  1113.             DragWindow( whichWindow, eventPtr->where, &qd.screenBits.bounds);
  1114.             break;
  1115.         case inGoAway: //• Just quit if user clicks in GoAway box; this is just a simple program.
  1116.             if(TrackGoAway(whichWindow, eventPtr->where))
  1117.                 gDone = true;
  1118.             break;
  1119.     }
  1120. }
  1121.  
  1122. //• BackIBeam()
  1123. void BackIBeam(void)
  1124. {
  1125.     EventRecord fakeEvt;
  1126.     
  1127.     TypeIt('(');
  1128.     TypeIt(')');
  1129.     //• Hmmm, this looks rather cryptic...
  1130.     fakeEvt.what = keyDown;
  1131.     fakeEvt.message = 162588;
  1132.     fakeEvt.modifiers = 128;
  1133.     doDlgEvt(&fakeEvt);
  1134. }
  1135.  
  1136. //• TypeIt()
  1137. void TypeIt(char c)
  1138. {
  1139.     EventRecord fakeEvt;
  1140.     long    it;
  1141.     
  1142.     switch(c)
  1143.     {
  1144.         case 'a':
  1145.             it = 131169;
  1146.             break;
  1147.         case 'b':
  1148.             it = 133986;
  1149.             break;
  1150.         case 's':
  1151.             it = 131443;
  1152.             break;
  1153.         case 'c':
  1154.             it = 133219;
  1155.             break;
  1156.         case 'o':
  1157.             it = 139119;
  1158.             break;
  1159.         case 'i':
  1160.             it = 139881;
  1161.             break;
  1162.         case 'n':
  1163.             it = 142702;
  1164.             break;
  1165.         case 't':
  1166.             it = 135540;
  1167.             break;
  1168.         case 'h':
  1169.             it = 132200;
  1170.             break;
  1171.         case 'e':
  1172.             it = 134757;
  1173.             break;
  1174.         case 'x':
  1175.             it = 132984;
  1176.             break;
  1177.         case 'p':
  1178.             it = 140144;
  1179.             break;
  1180.         case 'l':
  1181.             it = 140652;
  1182.             break;
  1183.         case 'g':
  1184.             it = 132455;
  1185.             break;
  1186.         case 'q':
  1187.             it = 134257;
  1188.             break;
  1189.         case 'r':
  1190.             it = 135026;
  1191.             break;
  1192.         case '0':
  1193.             it = 138544;
  1194.             break;
  1195.         case '1':
  1196.             it = 135729;
  1197.             break;
  1198.         case '2':
  1199.             it = 135986;
  1200.             break;
  1201.         case '3':
  1202.             it = 136243;
  1203.             break;
  1204.         case '4':
  1205.             it = 136500;
  1206.             break;
  1207.         case '5':
  1208.             it = 137013;
  1209.             break;
  1210.         case '6':
  1211.             it = 136758;
  1212.             break;
  1213.         case '7':
  1214.             it = 137783;
  1215.             break;
  1216.         case '8':
  1217.             it = 138296;
  1218.             break;
  1219.         case '9':
  1220.             it = 137529;
  1221.             break;
  1222.         case '.':
  1223.             it = 143150;
  1224.             break;
  1225.         case '(':
  1226.             it = 137512;
  1227.             break;
  1228.         case ')':
  1229.             it = 138537;
  1230.             break;
  1231.         case 'E':
  1232.             it = 134725;
  1233.             break;
  1234.         case '*':
  1235.             it = 138282;
  1236.             break;
  1237.         case '+':
  1238.             it = 137259;
  1239.             break;
  1240.         case '-':
  1241.             it = 138029;
  1242.             break;
  1243.         case '/':
  1244.             it = 142383;
  1245.             break;
  1246.         case '^':
  1247.             it = 136798;
  1248.             break;
  1249.         case '%':
  1250.             it = 136997;
  1251.             break;
  1252.         default:
  1253.             DoError("\pStefan forgot to fix something!", false);
  1254.             break;
  1255.         
  1256.     }
  1257.     //• Hmmm, this looks rather cryptic...
  1258.     fakeEvt.what = keyDown;
  1259.     fakeEvt.message = it;
  1260.     fakeEvt.modifiers = 640; //• = Shift Key
  1261.     doDlgEvt(&fakeEvt);
  1262. }
  1263.  
  1264. //• Credits()
  1265. void Credits(void)
  1266. {
  1267.     short    i;
  1268.     
  1269.     //• save current entry
  1270.     for(i=0; i<255; i++)
  1271.         saveStr[i] = expressionStr[i];
  1272.     DisposeDialog(dialog); //• Like I said, the main DLOG gets killed quite often...
  1273.     if(isPressed(58)) //• optionKey = 3A hex
  1274.         Alert(129, nil); //• Bonus easter egg!
  1275.     else
  1276.         Alert( 130, nil);
  1277.     DoMainDLOG(); //• ... and gets resurrected!
  1278. }
  1279.  
  1280. //• Help()
  1281. void Help(void)
  1282. {
  1283.     DisposeDialog(dialog); //• Like I said, the main DLOG gets killed quite often...
  1284.     Helper(); //• Here, refer to the separate file 'Help.c'
  1285.     DoMainDLOG(); //• ... and gets resurrected!
  1286. }
  1287.  
  1288. //• Again, my little secret!
  1289. double Solve(char infixStr[])
  1290. {
  1291.     double    answer;
  1292.     long garbage;
  1293.     short    i=0;
  1294.     
  1295.     while(infixStr[i] != '\0')
  1296.         garbage *= (int)infixStr[i++];
  1297.     answer = kPI * garbage;
  1298.     return answer;
  1299. }
  1300.     
  1301. void PleaseRegister(void)
  1302. {
  1303.     switch (Alert(kPleaseRegisterAlertNum, 0L)) 
  1304.     {
  1305.         case 1:
  1306.             Registration();
  1307.             break;
  1308.          case 2:    //• Cancel
  1309.              break;
  1310.      }
  1311. }
  1312.  
  1313. //• Registration()
  1314. void Registration(void)
  1315. {
  1316.     DialogPtr    rDialog;
  1317.     Boolean        done = false;
  1318.     Handle        itemHandle;
  1319.     Rect        itemRect;
  1320.     short        itemType, itemHit;
  1321.     Handle        okItemHandle, nameH, numH;
  1322.     Str255        nameStr, numStr;
  1323.     int            code, i=0, j, l;
  1324.     short        k;
  1325.     
  1326.     rDialog = GetNewDialog(kRegistrationDLOG, nil, (WindowPtr)-1L);
  1327.     ShowWindow(rDialog);
  1328.     SetPort(rDialog);
  1329.     
  1330.     GetDItem( rDialog, 1, &itemType, &okItemHandle, &itemRect);
  1331.     GetDItem( rDialog, 2, &itemType, &nameH, &itemRect);
  1332.     SelIText( rDialog, 2, kMinTextPosition, kMaxTextPosition);
  1333.     GetDItem( rDialog, 3, &itemType, &numH, &itemRect);
  1334.     
  1335.     SetDialogTracksCursor(rDialog, true);
  1336.     SetDialogDefaultItem(rDialog, ok);
  1337.     
  1338.     while(!done)
  1339.     {
  1340.         GetIText( nameH, nameStr);
  1341.         if( nameStr[0] == 0)
  1342.             HiliteControl((ControlHandle)okItemHandle, 255);
  1343.         else
  1344.             HiliteControl((ControlHandle)okItemHandle, 0);
  1345.         ModalDialog( nil, &itemHit);
  1346.         if(itemHit == ok)
  1347.         {
  1348.             GetDItem( rDialog, 2, &itemType, &nameH, &itemRect);
  1349.             GetIText( nameH, nameStr);
  1350.             j = strlen(p2cstr(nameStr));
  1351.             if(j < kMinNameLength)
  1352.             {
  1353.                 DoError("\pThat name is invalid - too short!", false);
  1354.                 goto skippy; //• Yuck, a 'goto' statement!
  1355.             }
  1356.             GetDItem( rDialog, 3, &itemType, &numH, &itemRect);
  1357.             GetIText( numH, numStr);
  1358.             l = strlen(p2cstr(numStr));
  1359.             if(j != l)
  1360.             {
  1361.                 DoError("\pInvalid registration combination!", false);
  1362.                 goto skippy;
  1363.             }
  1364.             //• I cut out my secret registration code here!
  1365.             DoError("\pInvalid registration combination!", false);
  1366.             goto skippy; //• Uh oh, another 'goto' statement!
  1367.             //• If you make it this far, you are registered!
  1368.             //• gRegistered = true;
  1369.             done = true;
  1370.         }
  1371.     }
  1372.     skippy:
  1373.     DisposeDialog(rDialog);
  1374. }